package com.bleeth.fx.meta;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.watch.SimpleWatcher;
import cn.hutool.core.io.watch.WatchMonitor;
import cn.hutool.core.io.watch.WatchUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.StrUtil;
import com.bleeth.fx.helper.AppHelper;
import com.bleeth.fx.layout.FormBuilder;
import javafx.application.Platform;
import javafx.beans.property.Property;
import javafx.scene.layout.Region;

import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 视图路由器 是通过路由将视图放入容器中，且容器可以灵活切换视图
 *
 * @author BleethNie
 * @version 1.0
 * @date 2021-11-13 22:44
 **/
public class ViewRouter {

    private String router;

    private FormBuilder.RowBuilder rowBuilder;

    private Integer cellIndex;

    private String type;

    private StyleFunction style;



    /**
     * 路由和视图映射器
     */
    private static final Map<String, IForm> viewMap = new HashMap();

    /**
     * 路由和容器映射器
     */
    private static final Map<String, ViewRouter> routerMap = new HashMap();

    private static IForm beginForm;


    private static String DEFAULT_TARGET = System.getProperty("user.dir") + "/target";

    private static Set<Class<?>> classSet;

    public static void scan(String packageName) {
        Set<Class<?>> clazzSet = ClassUtil.scanPackageByAnnotation(packageName, View.class);
        classSet = CollUtil.newHashSet(clazzSet);
        List<Class<?>> classList = classSet.stream().collect(Collectors.toList());
        for (int i = 0; i < classList.size(); i++) {
            Class<?> iFormClazz = classList.get(i);
            View view = iFormClazz.getAnnotation(View.class);
            String type = view.type();
            String value = view.value();
            Class<IForm> iFormClass = (Class<IForm>) iFormClazz;
            try {
                IForm iform = iFormClass.newInstance();
                iform.init();
                viewMap.put(value, iform);
                if (StrUtil.equalsIgnoreCase(type, "begin")) {
                    beginForm = iform;
                }
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    //切换到下一个页面
    public Region push(String router, Property... properties) {
        Console.log("查询视图{}", router);
        IForm iForm = viewMap.get(router);
        if (iForm == null) {
            throw new RuntimeException("未找到对应的视图");
        }
        Region region = iForm.make(properties);
        if (style != null) {
            style.style(region);
        }
        return region;
    }

    public static void change(String vRouter, String formRouter) {
        ViewRouter viewRouter = routerMap.get(vRouter);
        IForm iForm = viewMap.get(formRouter);
        viewRouter.rowBuilder.clearCell(viewRouter.cellIndex);
        if (StrUtil.equalsIgnoreCase(viewRouter.type, "COVER")) {
            viewRouter.rowBuilder.coverCell(viewRouter.cellIndex, iForm.make());
        } else {
            viewRouter.rowBuilder.addCell(viewRouter.cellIndex, iForm.make());
        }
    }

    public static void change(String vRouter, Region region) {
        ViewRouter viewRouter = routerMap.get(vRouter);
        viewRouter.rowBuilder.clearCell(viewRouter.cellIndex);
        if (StrUtil.equalsIgnoreCase(viewRouter.type, "COVER")) {
            viewRouter.rowBuilder.coverCell(viewRouter.cellIndex, region);
        } else {
            viewRouter.rowBuilder.addCell(viewRouter.cellIndex, region);
        }
    }

    public static void monitor() {
        final int[] time = {0};
        WatchMonitor monitor = WatchUtil.createAll(DEFAULT_TARGET, 10, new SimpleWatcher() {

            @Override
            public void onCreate(WatchEvent<?> event, Path currentPath) {
                System.err.println("onCreate");
            }

            @Override
            public void onDelete(WatchEvent<?> event, Path currentPath) {
                System.err.println("onDelete");
            }

            @Override
            public void onModify(WatchEvent<?> event, Path currentPath) {
                Platform.runLater(() -> {
                    System.err.println("热更新...");
                    AppHelper.showForm(beginForm.make(), null, "");
                });
            }
        });
        monitor.setDaemon(true);
        monitor.start();
    }

    public static void start() {
        if (beginForm == null) {
            throw new RuntimeException("未找到初始化视图");
        }
        AppHelper.showForm(beginForm.make(), null, "");
        monitor();
    }


    public static ViewRouter of(String router) {
        return ViewRouter.builder().router(router);
    }

    public ViewRouter rowBuilder(FormBuilder.RowBuilder rowBuilder) {
        this.rowBuilder = rowBuilder;
        return this;
    }

    public ViewRouter index(Integer cellIndex) {
        this.cellIndex = cellIndex;
        return this;
    }

    public ViewRouter type(String type) {
        this.type = type;
        return this;
    }

    public ViewRouter router(String router) {
        this.router = router;
        return this;
    }

    public ViewRouter style(StyleFunction style) {
        this.style = style;
        return this;
    }

    public static ViewRouter builder() {
        ViewRouter router = new ViewRouter();
        return router;
    }

    public void make() {
        routerMap.put(router, this);
    }
}
